; vim:ts=4:sw=4:et:
; PRINT command routine
; Does not print attribute. Use PRINT_STR or PRINT_NUM for that
;
#include once <sposn.asm>
#include once <cls.asm>
#include once <in_screen.asm>
#include once <table_jump.asm>
#include once <ink.asm>
#include once <paper.asm>
#include once <flash.asm>
#include once <bright.asm>
#include once <over.asm>
#include once <inverse.asm>
#include once <bold.asm>
#include once <italic.asm>
#include once <const.asm>
#include once <attr.asm>
;
; Putting a comment starting with @INIT <address>
; will make the compiler to add a CALL to <address>
; It is useful for initialization routines.
#init __PRINT_INIT
;
__PRINT_INIT: ; To be called before program starts (initializes library)
                     ;- PROC
                     ;- ld hl, __PRINT_START
                     ;- ld (PRINT_JUMP_STATE), hl
                     ;- ld hl, 1821h
                     ;- ld (MAXX), hl  ; Sets current maxX and maxY

eor z80_a            ;- xor a
                     ;- ld (FLAGS2), a
rts                       ;- ret

__PRINTCHAR:
; Print character store in accumulator (A register)
; Modifies H'L', B'C', A'F', D'E', A
                     ;- LOCAL PO_GR_1
                     ;- LOCAL __PRCHAR
                     ;- LOCAL __PRINT_CONT
                     ;- LOCAL __PRINT_CONT2
                     ;- LOCAL __PRINT_JUMP
                     ;- LOCAL __SRCADDR
                     ;- LOCAL __PRINT_UDG
                     ;- LOCAL __PRGRAPH
                     ;- LOCAL __PRINT_START

PRINT_JUMP_STATE EQU __PRINT_JUMP + 1

__PRINT_JUMP:
jmp __PRINT_START    ;- jp __PRINT_START    ; Where to jump. If we print 22 (AT), next two calls jumps to AT1 and AT2 respectively

__PRINT_START:
                     ;- cp ' '
                     ;- jp c, __PRINT_SPECIAL    ; Characters below ' ' are special ones
                     ;- exx            ; Switch to alternative registers
                     ;- ex af, af'        ; Saves a value (char to print) for later
jsr __LOAD_S_POSN    ;- call __LOAD_S_POSN

; At this point we have the new coord
                     ;- ld hl, (SCREEN_ADDR)
                     ;- ld a, d
                     ;- ld c, a        ; Saves it for later
                     ;- and 0F8h    ; Masks 3 lower bit ; zy
                     ;- ld d, a
                     ;- ld a, c        ; Recovers it
                     ;- and 07h     ; MOD 7 ; y1
                     ;- rrca
                     ;- rrca
                     ;- rrca
                     ;- or e
                     ;- ld e, a
                     ;- add hl, de    ; HL = Screen address + DE
                     ;- ex de, hl     ; DE = Screen address
                     ;- ex af, af'
                     ;- cp 80h    ; Is it an UDG or a ?
                     ;- jp c, __SRCADDR
                     ;- cp 90h
                     ;- jp nc, __PRINT_UDG
; Print a 8 bit pattern (80h to 8Fh)
                     ;- ld b, a
                     ;- call PO_GR_1 ; This ROM routine will generate the bit pattern at MEM0
                     ;- ld hl, MEM0
                     ;- jp __PRGRAPH

PO_GR_1 EQU 0B38h

__PRINT_UDG:
                     ;- sub 90h ; Sub ASC code
                     ;- ld bc, (UDG)
                     ;- jp __PRGRAPH0

__SOURCEADDR EQU (__SRCADDR + 1)    ; Address of the pointer to chars source
__SRCADDR:
                     ;- ld bc, (CHARS)

__PRGRAPH0:
                     ;- add a, a    ; A = a * 2 (since a < 80h) ; Thanks to Metalbrain at http://foro.speccy.org
                     ;- ld l, a
                     ;- ld h, 0        ; HL = a * 2 (accumulator)
                     ;- add hl, hl
                     ;- add hl, hl ; HL = a * 8
                     ;- add hl, bc ; HL = CHARS address

__PRGRAPH:
                     ;- ex de, hl  ; HL = Write Address, DE = CHARS address
                     ;- bit 2, (iy + $47)
                     ;- call nz, __BOLD
                     ;- bit 4, (iy + $47)
                     ;- call nz, __ITALIC
                     ;- ld b, 8 ; 8 bytes per char
__PRCHAR:
                     ;- ld a, (de) ; DE *must* be ALWAYS source, and HL destiny

PRINT_MODE:        ; Which operation is used to write on the screen
                     ;-         ; Set it with:
                     ;-         ; LD A, <OPERATION>
                     ;-         ; LD (PRINT_MODE), A
                     ;-         ;
                     ;-         ; Available opertions:
                     ;-         ; NORMAL: 0h  --> NOP    ; OVER 0
                     ;-         ; XOR    : AEh --> XOR (HL)        ; OVER 1
                     ;-         ; OR    : B6h --> OR (HL)        ; PUTSPRITE
                     ;-         ; AND   : A6h --> AND (HL)        ; PUTMASK
                     ;- nop        ;

INVERSE_MODE:    ; 00 -> NOP -> INVERSE 0
                     ;- nop        ; 2F -> CPL -> INVERSE 1
                     ;- ld (hl), a
                     ;- inc de
                     ;- inc h     ; Next line
                     ;- djnz __PRCHAR
jsr __LOAD_S_POSN    ;- call __LOAD_S_POSN
                     ;- push de
jsr __SET_ATTR       ;- call __SET_ATTR
                     ;- pop de
                     ;- inc e            ; COL = COL + 1
                     ;- ld hl, (MAXX)
                     ;- ld a, e
                     ;- dec l            ; l = MAXX
                     ;- cp l            ; Lower than max?
                     ;- jp c, __PRINT_CONT; Nothing to do
jsr __PRINT_EOL1     ;- call __PRINT_EOL1
                     ;- exx            ; counteracts __PRINT_EOL1 exx
jmp __PRINT_CONT2    ;- jp __PRINT_CONT2

__PRINT_CONT:
                     ;- call __SAVE_S_POSN

__PRINT_CONT2:
                     ;- exx
rts                  ;- ret

; ------------- SPECIAL CHARS (< 32) -----------------

__PRINT_SPECIAL:    ; Jumps here if it is a special char
                     ;- exx
                     ;- ld hl, __PRINT_TABLE
jmp JUMP_HL_PLUS_2A  ;- jp JUMP_HL_PLUS_2A


PRINT_EOL:        ; Called WHENEVER there is no ";" at end of PRINT sentence
                     ;- exx

__PRINT_0Dh:      ; Called WHEN printing CHR$(13)
jsr __LOAD_S_POSN    ;- call __LOAD_S_POSN

__PRINT_EOL1:        ; Another entry called from PRINT when next line required
                     ;- ld e, 0

__PRINT_EOL2:
                     ;- ld a, d
clc                  ;- inc a
adc #$01

__PRINT_AT1_END:
                     ;- ld hl, (MAXY)
cmp z80_l            ;- cp l
                     ;- jr c, __PRINT_EOL_END    ; Carry if (MAXY) < d
eor z80_a            ;- xor a

__PRINT_EOL_END:
                     ;- ld d, a

__PRINT_AT2_END:
jsr __SAVE_S_POSN    ;- call __SAVE_S_POSN
lda z80_c            ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
rts                  ;- ret

__PRINT_COM:
lda z80_c            ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
                     ;- push hl
lda z80_e            ;- push de
pha
lda z80_d
pha
lda z80_c                ;- push bc
pha
lda z80_b
pha
jsr PRINT_COMMA          ;- call PRINT_COMMA
pla                      ;- pop bc
sta z80_b
pla
sta z80_c
pla                      ;- pop de
sta z80_d
pla
sta z80_e
pla                      ;- pop hl
sta z80_h
pla
sta z80_l
rts                      ;- ret

__PRINT_TAB:
                         ;- ld hl, __PRINT_TAB1
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_TAB1:
                         ;- ld (MEM0), a
                         ;- ld hl, __PRINT_TAB2
                         ;- ld (PRINT_JUMP_STATE), hl
rts                      ;- ret

__PRINT_TAB2:
                         ;- ld a, (MEM0)        ; Load tab code (ignore the current one)
lda z80_l                ;- push hl
pha
lda z80_h
pha
lda z80_e                ;- push de
pha
lda z80_d
pha
lda z80_c                ;- push bc
pha
lda z80_b
pha
                         ;- ld hl, __PRINT_START
                         ;- ld (PRINT_JUMP_STATE), hl
jsr PRINT_TAB            ;- call PRINT_TAB
pla                      ;- pop bc
sta z80_b
pla
sta z80_c
                         ;- pop de
                         ;- pop hl
rts                      ;- ret

__PRINT_NOP:
__PRINT_RESTART:
                         ;- ld hl, __PRINT_START
                         ;- jp __PRINT_SET_STATE

__PRINT_AT:
                         ;- ld hl, __PRINT_AT1

__PRINT_SET_STATE:
                     ;- ld (PRINT_JUMP_STATE), hl    ; Saves next entry call
lda z80_c            ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
rts                  ;- ret

__PRINT_AT1:    ; Jumps here if waiting for 1st parameter
lda z80_c            ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
                     ;- ld hl, __PRINT_AT2
                     ;- ld (PRINT_JUMP_STATE), hl    ; Saves next entry call
jsr __LOAD_S_POSN    ;- call __LOAD_S_POSN
jmp __PRINT_AT1_END  ;- jp __PRINT_AT1_END

__PRINT_AT2:
lda z80_c            ;- exx
ldx z80_cp
stx z80_c
sta z80_cp
lda z80_b
ldx z80_bp
stx z80_b
sta z80_bp
lda z80_e
ldx z80_ep
stx z80_e
sta z80_ep
lda z80_d
ldx z80_dp
stx z80_d
sta z80_dp
lda z80_l
ldx z80_lp
stx z80_l
sta z80_lp
lda z80_h
ldx z80_hp
stx z80_h
sta z80_hp
                         ;- ld hl, __PRINT_START
                         ;- ld (PRINT_JUMP_STATE), hl    ; Saves next entry call
jsr __LOAD_S_POSN                     ;- call __LOAD_S_POSN
                         ;- ld e, a
                         ;- ld hl, (MAXX)
                         ;- cp (hl)
                         ;- jr c, __PRINT_AT2_END
                         ;- jr __PRINT_EOL1

__PRINT_DEL:
                         ;- call __LOAD_S_POSN        ; Gets current screen position
                         ;- dec e
                         ;- ld a, -1
                         ;- cp e
                         ;- jp nz, __PRINT_AT2_END
                         ;- ld hl, (MAXX)
                         ;- ld e, l
                         ;- dec e
                         ;- dec e
                         ;- dec d
                         ;- cp d
                         ;- jp nz, __PRINT_AT2_END
                         ;- ld d, h
                         ;- dec d
jmp __PRINT_AT2_END      ;- jp __PRINT_AT2_END

__PRINT_INK:
                         ;- ld hl, __PRINT_INK2
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_INK2:
                         ;- exx
jsr INK_TMP              ;- call INK_TMP
jmp __PRINT_RESTART      ;- jp __PRINT_RESTART

__PRINT_PAP:
                         ;- ld hl, __PRINT_PAP2
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_PAP2:
                         ;- exx
jsr PAPER_TMP            ;- call PAPER_TMP
jmp __PRINT_RESTART      ;- jp __PRINT_RESTART

__PRINT_FLA:
                         ;- ld hl, __PRINT_FLA2
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_FLA2:
                         ;- exx
jsr FLASH_TMP            ;- call FLASH_TMP
jmp __PRINT_RESTART      ;- jp __PRINT_RESTART

__PRINT_BRI:
                         ;- ld hl, __PRINT_BRI2
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_BRI2:
                         ;- exx
jsr BRIGHT_TMP           ;- call BRIGHT_TMP
jmp __PRINT_RESTART      ;- jp __PRINT_RESTART

__PRINT_INV:
                         ;- ld hl, __PRINT_INV2
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_INV2:
                         ;- exx
jsr INVERSE_TMP          ;- call INVERSE_TMP
jmp __PRINT_RESTART      ;- jp __PRINT_RESTART

__PRINT_OVR:
                         ;- ld hl, __PRINT_OVR2
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_OVR2:
                         ;- exx
                         ;- call OVER_TMP
jmp __PRINT_RESTART      ;- jp __PRINT_RESTART

__PRINT_BOLD:
                         ;- ld hl, __PRINT_BOLD2
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_BOLD2:
                         ;- exx
jsr BOLD_TMP            ;- call BOLD_TMP
jmp __PRINT_RESTART      ;- jp __PRINT_RESTART

__PRINT_ITA:
                         ;- ld hl, __PRINT_ITA2
jmp __PRINT_SET_STATE    ;- jp __PRINT_SET_STATE

__PRINT_ITA2:
                         ;- exx
jsr ITALIC_TMP           ;- call ITALIC_TMP
jmp __PRINT_RESTART      ;- jp __PRINT_RESTART


__BOLD:
lda z80_l            ;- push hl
pha
lda z80_h
pha
                     ;- ld hl, MEM0
                     ;- ld b, 8
__BOLD_LOOP:
                     ;- ld a, (de)
                     ;- ld c, a
                     ;- rlca
                     ;- or c
                     ;- ld (hl), a
                     ;- inc hl
                     ;- inc de
                     ;- djnz __BOLD_LOOP
                     ;- pop hl
                     ;- ld de, MEM0
rts                  ;- ret


__ITALIC:
lda z80_l            ;- push hl
pha
lda z80_h
pha
                     ;- ld hl, MEM0
                     ;- ex de, hl
                     ;- ld bc, 8
                     ;- ldir
                     ;- ld hl, MEM0
                     ;- srl (hl)
                     ;- inc hl
                     ;- srl (hl)
                     ;- inc hl
                     ;- srl (hl)
                     ;- inc hl
                     ;- inc hl
                     ;- inc hl
                     ;- sla (hl)
                     ;- inc hl
                     ;- sla (hl)
                     ;- inc hl
                     ;- sla (hl)
                     ;- pop hl
                     ;- ld de, MEM0
rts                  ;- ret

PRINT_COMMA:
jsr __LOAD_S_POSN    ;- call __LOAD_S_POSN
                     ;- ld a, e
                     ;- and 16
                     ;- add a, 16

PRINT_TAB:
                     ;- PROC
                     ;- LOCAL LOOP, CONTINUE

                     ;- inc a
                     ;- call __LOAD_S_POSN ; e = current row
lda z80_a            ;- ld d,a
sta z80_d
                     ;- ld a, e
                     ;- cp 21h
                     ;- jr nz, CONTINUE
                     ;- ld e, -1
CONTINUE:
                     ;- ld a, d
                     ;- inc e
                     ;- sub e  ; A = A - E
                     ;- and 31 ;
                     ;- ret z  ; Already at position E
                     ;- ld b, a
LOOP:
                     ;- ld a, ' '
                     ;- call __PRINTCHAR
                     ;- djnz LOOP
                     ;- ret
                     ;- ENDP

PRINT_AT: ; CHanges cursor to ROW, COL
                     ;-  ; COL in A register
                     ;-  ; ROW in stack
                     ;- pop hl    ; Ret address
                     ;- ex (sp), hl ; callee H = ROW
                     ;- ld l, a
                     ;- ex de, hl
jsr __IN_SCREEN      ;- call __IN_SCREEN
                     ;- ret nc    ; Return if out of screen
                     ;- jp __SAVE_S_POSN
                     ;- LOCAL __PRINT_COM
                     ;- LOCAL __BOLD
                     ;- LOCAL __BOLD_LOOP
                     ;- LOCAL __ITALIC
                     ;- LOCAL __PRINT_EOL1
                     ;- LOCAL __PRINT_EOL2
                     ;- LOCAL __PRINT_AT1
                     ;- LOCAL __PRINT_AT2
                     ;- LOCAL __PRINT_AT2_END
                     ;- LOCAL __PRINT_BOLD
                     ;- LOCAL __PRINT_BOLD2
                     ;- LOCAL __PRINT_ITA
                     ;- LOCAL __PRINT_ITA2
                     ;- LOCAL __PRINT_INK
                     ;- LOCAL __PRINT_PAP
                     ;- LOCAL __PRINT_SET_STATE
                     ;- LOCAL __PRINT_TABLE
                     ;- LOCAL __PRINT_TAB, __PRINT_TAB1, __PRINT_TAB2

__PRINT_TABLE:    ; Jump table for 0 .. 22 codes
                     ;- DW __PRINT_NOP    ;  0
                     ;- DW __PRINT_NOP    ;  1
                     ;- DW __PRINT_NOP    ;  2
                     ;- DW __PRINT_NOP    ;  3
                     ;- DW __PRINT_NOP    ;  4
                     ;- DW __PRINT_NOP    ;  5
                     ;- DW __PRINT_COM    ;  6 COMMA
                     ;- DW __PRINT_NOP    ;  7
                     ;- DW __PRINT_DEL    ;  8 DEL
                     ;- DW __PRINT_NOP    ;  9
                     ;- DW __PRINT_NOP    ; 10
                     ;- DW __PRINT_NOP    ; 11
                     ;- DW __PRINT_NOP    ; 12
                     ;- DW __PRINT_0Dh    ; 13
                     ;- DW __PRINT_BOLD    ; 14
                     ;- DW __PRINT_ITA    ; 15
                     ;- DW __PRINT_INK    ; 16
                     ;- DW __PRINT_PAP    ; 17
                     ;- DW __PRINT_FLA    ; 18
                     ;- DW __PRINT_BRI    ; 19
                     ;- DW __PRINT_INV    ; 20
                     ;- DW __PRINT_OVR    ; 21
                     ;- DW __PRINT_AT    ; 22 AT
                     ;- DW __PRINT_TAB  ; 23 TAB
                     ;- ENDP

